package com.gpscookie.vocabularystory;

import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
import android.widget.CompoundButton;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ToggleButton;

public class MainScreen extends AbstractActivity {
	private ListView list;
	private EntryListAdapter adapter;
	private ArrayList<Entry> entries;
	private boolean isLastPage = false;
	private boolean isFirstPage = false;
	private ToggleButton btnPrevious;
	private ToggleButton btnNext;
	private ToggleButton btnPlay;
	private ToggleButton btnHide;
	private ToggleButton btnFilter;
	private boolean isHide = false;
	private int filter = 0;
	private TextView txtFootage;
	private int totalPages;
	private int totalFilterPages;
	private int currentFilterPage;
	private int totalFilterWords;
	private static final int MAXLEVEL = 9;
	private static String pageHead = "%d/%d";
	
	@Override
	public void onPause() {
		super.onPause();
		// save the entries
		saveEntries();
		// save the book entry
		SimpleDBHelper db = new SimpleDBHelper(this);
		db.saveBook(Utils.INSTANCE.currentBook);
		db.close();
	}
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        txtFootage = (TextView)findViewById(R.id.txtfootage);
        totalPages = 0;
        if (Utils.INSTANCE.currentBook.getTotal()%Utils.INSTANCE.pageSize==0) {
        	totalPages = Utils.INSTANCE.currentBook.getTotal()/Utils.INSTANCE.pageSize;
        } else {
        	totalPages = Utils.INSTANCE.currentBook.getTotal()/Utils.INSTANCE.pageSize + 1;
        }
        
        entries = new ArrayList<Entry>();
        list = (ListView)findViewById(R.id.entrylist);
        adapter = new EntryListAdapter(this);
        list.setAdapter(adapter);
        list.setOnItemLongClickListener(new OnItemLongClickListener(){
			public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
					int pos, long arg3) {
				if (Utils.INSTANCE.tts != null) {
					Entry entry = entries.get(pos);
					Utils.INSTANCE.tts.speak(entry.getEntry(), TextToSpeech.QUEUE_FLUSH, null);
				return true;
				} else {
					return false;
				}
			}
        });
        list.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> arg0, View arg1, int pos,
					long arg3) {
				Entry entry = entries.get(pos);
				Intent it = new Intent(MainScreen.this, EntryScreen.class);				
				it.putExtra("entry", entry.getEntry());
				it.putExtra("desc", entry.getDesc());
				it.putExtra("key", entry.getKey());
				it.putExtra("level", entry.getLevel());
				it.putExtra("shortdesc", entry.getShortdesc());
				it.putExtra("url", entry.getUrl());
				it.putExtra("voice", entry.getVoice());
				startActivity(it);
			}
		});
        
        btnPrevious = (ToggleButton)findViewById(R.id.btnprevious);
        btnPrevious.setOnClickListener(new OnClickListener(){
			public void onClick(View arg0) {
				if (filter>0) {
					if (currentFilterPage>1) {
						currentFilterPage--;
					}
					txtFootage.setText(String.format(pageHead, currentFilterPage, totalFilterPages));
			        setBusy(true);
			        saveEntries();
			        new EntryDownloadTask().execute(currentFilterPage);					
				} else {
					int current = Utils.INSTANCE.currentBook.getCurrent();
					if (current>1) {
						Utils.INSTANCE.currentBook.setCurrent(current-1);
					}
					txtFootage.setText(String.format(pageHead, Utils.INSTANCE.currentBook.getCurrent(), totalPages));
			        setBusy(true);
			        saveEntries();
			        new EntryDownloadTask().execute(Utils.INSTANCE.currentBook.getCurrent());
				}
			}});
        
        btnNext = (ToggleButton)findViewById(R.id.btnnext);
        btnNext.setOnClickListener(new OnClickListener(){
			public void onClick(View arg0) {
				if (filter>0) {
					if (currentFilterPage<totalFilterPages) {
						currentFilterPage++;
					}
					txtFootage.setText(String.format(pageHead, currentFilterPage, totalFilterPages));
			        setBusy(true);
			        saveEntries();
			        new EntryDownloadTask().execute(currentFilterPage);					
				} else {				
					int current = Utils.INSTANCE.currentBook.getCurrent();
					if (current<totalPages) {
						Utils.INSTANCE.currentBook.setCurrent(current+1);
					}
					txtFootage.setText(String.format(pageHead, Utils.INSTANCE.currentBook.getCurrent(), totalPages));
			        setBusy(true);
			        saveEntries();
			        new EntryDownloadTask().execute(Utils.INSTANCE.currentBook.getCurrent());
				}
			}});
        
        btnPlay = (ToggleButton)findViewById(R.id.btnplay);
        btnPlay.setOnClickListener(new OnClickListener(){
			public void onClick(View arg0) {
				Intent it = new Intent(MainScreen.this, PlayScreen.class);
				it.putExtra("filter", filter);				
				it.putExtra("hide", isHide);
				if (filter>0) {
					it.putExtra("current", currentFilterPage);
				} else {
					it.putExtra("current", Utils.INSTANCE.currentBook.getCurrent());
				}
				startActivity(it);
			}});
        
        btnHide = (ToggleButton)findViewById(R.id.btnhide);
        btnHide.setOnCheckedChangeListener(new OnCheckedChangeListener(){
			public void onCheckedChanged(CompoundButton buttonView,
					boolean isChecked) {
				isHide = !isHide;
				adapter.notifyDataSetInvalidated();
			}});
        
        btnFilter = (ToggleButton)findViewById(R.id.btnfilter);
        btnFilter.setOnCheckedChangeListener(new OnCheckedChangeListener() {
        	public void onCheckedChanged(CompoundButton buttonView,
					boolean isChecked) {
				setBusy(true);
				// toggle filter
				if (filter>0) {
					filter = 0;
				} else {
					filter = 1;
				}
				saveEntries();
				
				if (filter>0) {
					currentFilterPage = 1;
					SimpleDBHelper db = new SimpleDBHelper(MainScreen.this);
					totalFilterWords = db.countEntryList(Utils.INSTANCE.currentBook.getKey(), filter);
					db.close();
			        if (totalFilterWords%Utils.INSTANCE.pageSize==0) {
			        	totalFilterPages = totalFilterWords/Utils.INSTANCE.pageSize;
			        } else {
			        	totalFilterPages = totalFilterWords/Utils.INSTANCE.pageSize + 1;
			        }				
					// reset to page one	
			        txtFootage.setText(String.format(pageHead, currentFilterPage, totalFilterPages));
					new EntryDownloadTask().execute(currentFilterPage);
				} else {
					txtFootage.setText(String.format(pageHead, Utils.INSTANCE.currentBook.getCurrent(), totalPages));
					new EntryDownloadTask().execute(Utils.INSTANCE.currentBook.getCurrent());
				}
			}});
        
        setBusy(true);
		// Init. book table
		SimpleDBHelper db = new SimpleDBHelper(MainScreen.this);
		Book book = db.queryBook(Utils.INSTANCE.currentBook.getKey());
		if (book==null) {
			// a new book
			Utils.INSTANCE.currentBook.setCurrent(1);
		} else {
			Utils.INSTANCE.currentBook.setCurrent(book.getCurrent());
			this.setTitle(book.getTitle());
		}
		db.close();
		
        txtFootage.setText(String.format(pageHead, Utils.INSTANCE.currentBook.getCurrent(), totalPages));
        new EntryDownloadTask().execute(Utils.INSTANCE.currentBook.getCurrent());
        
    }
    
    private void saveEntries() {
    	SimpleDBHelper db = new SimpleDBHelper(this);
    	for (int i=0; i<entries.size(); i++) {
    		db.saveEntry(entries.get(i));
    	}
    	db.close();
    }
    
    private class EntryDownloadTask extends AsyncTask<Integer, Void, ArrayList<Entry>> {
    	
    	private ArrayList<Entry> queryEntryListFromWeb(Book book, ArrayList<Entry> items, int currentPage, SimpleDBHelper db) {
    		if (currentPage == totalPages && totalPages>1) {
    			// last page, don't fetch
    			return items;
    		} else {
    			if (items.size()==Utils.INSTANCE.pageSize) {
    				// found on local db, return
    				Log.i("MainScreen:EntryDownloadTask:queryEntryListFromWeb():", "found on local DB");    				
    			} else {
    				int offset = (currentPage-1)*Utils.INSTANCE.pageSize;
    				Log.i("MainScreen:EntryDownloadTask:queryEntryListFromWeb():", "next page is not complete on local");
    				JSONObject result = db.getJSON(Utils.INSTANCE.composeEntryListURL(
    						book.getKey(),
    						Utils.INSTANCE.pageSize*Utils.INSTANCE.pageNum, offset), true);
    				Log.i("MainScreen:EntryDownloadTask:queryEntryListFromWeb():", result.toString());
    				if (Utils.INSTANCE.getJSONResultError(result)==0) {
    					// entries returned
    					JSONArray array = Utils.INSTANCE.getJSONResultArray(result);
    					if (array!=null) {
    						// fetch the list and save on the local DB							
    						Log.i("MainScreen:EntryDownloadTask:queryEntryListFromWeb():", "save entry list "+array.length());
    						for (int i=0; i<array.length(); i++) {
    							try { 
    								JSONObject row = array.getJSONObject(i);
    								String key = book.getKey();
    								String entry = row.getString("entry");
    								String url = row.getString("url");
    								String shortdesc = row.getString("shortdescription");
    								String desc = row.getString("description");		
    								String voice = row.getString("voice");
    								Entry obj = new Entry();
    								obj.setVoice(voice);
    								obj.setLevel(-1);
    								obj.setKey(key);
    								obj.setEntry(entry);
    								obj.setUrl(url);
    								obj.setShortdesc(shortdesc);
    								obj.setDesc(desc);									
    								db.saveEntry(obj);	//save on db
    							} catch (JSONException e) {
    								// TODO Auto-generated catch block
    								e.printStackTrace();
    							}
    						}// for
    						// get from local DB again
    						items.clear();
    						items = db.queryEntryList(book.getKey(), currentPage, Utils.INSTANCE.pageSize, filter);
    						Log.i("MainScreen:EntryDownloadTask:queryEntryListFromWeb():", "get entry list "+items.size());
    					} else {
    						Log.i("MainScreen:EntryDownloadTask:queryEntryListFromWeb():", "empty array");
    						items.clear();
    					}
    				}    				
    			}
    			return items;
    		}
    	}

		@Override
		protected ArrayList<Entry> doInBackground(Integer... params) {
			int currentPage = params[0];
			Log.i("MainScreen:EntryDownloadTask:doInBackground():", "currentPage "+currentPage);			
			ArrayList<Entry> items = new ArrayList<Entry>();
			if (Utils.INSTANCE.currentBook==null) {
				// The current book is not set, return
				items = null;
			} else {
				SimpleDBHelper db = new SimpleDBHelper(MainScreen.this);
				Book book = Utils.INSTANCE.currentBook;
				// Init. entry table
				// query entry after current book entry position
				// query local db first
				items = db.queryEntryList(book.getKey(), currentPage, Utils.INSTANCE.pageSize, filter);
				db.close();
				if (filter>0) {
					// filter mode
					Log.i("MainScreen:EntryDownloadTask:doInBackground():", "filter level "+filter);
					// disable or enable buttons
					if (currentFilterPage==1) {
						// met the first page
						isFirstPage = true;					
					}
					if (currentFilterPage==totalFilterPages) {
						// met the last page
						isLastPage = true;					
					}
					if (currentFilterPage>1 && currentFilterPage<totalFilterPages) {
						// met the last page
						isLastPage = false;
						isFirstPage = false;
					}
				} else {
					items = queryEntryListFromWeb(book, items, currentPage, db);
					// disable or enable buttons
					if (currentPage==1) {
						// met the first page
						isFirstPage = true;					
					}
					if (currentPage==totalPages) {
						// met the last page
						isLastPage = true;					
					}
					if (currentPage>1 && currentPage<totalPages) {
						// met the last page
						isLastPage = false;
						isFirstPage = false;
					}					
				}
			}
			return items;
		}
		
		@Override
		protected void onPostExecute(ArrayList<Entry> result) {
			boolean error = false;
			if (result!=null) {
				Log.i("MainScreen:EntryDownloadTask:onPostExecute():", 
						String.format("isFirstPage:%b, isLastPage:%b, result size:%d", isFirstPage, isLastPage, result.size()));
				if (isFirstPage) {
					btnPrevious.setEnabled(false);
				} else {
					btnPrevious.setEnabled(true);
				}
				if (isLastPage) {
					btnNext.setEnabled(false);
				} else {
					btnNext.setEnabled(true);
				}
				if (filter>0 || result.size()>0) {
					// if in filter mode, or items returned
					entries.clear();
					entries = result;
					adapter.notifyDataSetChanged();
				}
				if (filter==0 && result.size()==0) {
					// no data returned
					error = true;
				}
			} else {
				Toast.makeText(MainScreen.this, 
						getString(R.string.unknownerror),
						Toast.LENGTH_LONG).show();
				error = true;
			}
			setBusy(false);
			if (error) {
				AlertDialog msg = new AlertDialog.Builder(MainScreen.this).create();
				msg.setButton(getString(R.string.btngoto), new DialogInterface.OnClickListener(){
					public void onClick(DialogInterface dialog, int which) {
						Intent browserIntent = new Intent("android.intent.action.VIEW", Uri.parse(Utils.INSTANCE.composeBookListHTMLURL()));
						startActivity(browserIntent);						
					}});
				msg.setMessage(getString(R.string.msgmanual));
				msg.setTitle(getString(R.string.error));
				msg.show();
			}
		}
    }
    
    private class EntryListAdapter extends BaseAdapter {
		private Context context;
		private LayoutInflater inflater;

		public EntryListAdapter(Context c) {
			context = c;
			inflater = LayoutInflater.from(context);
		}

		public int getCount() {
			return entries.size();
		}

		public Object getItem(int p) {
			return entries.get(p);
		}

		public long getItemId(int position) {
			return position;
		}

		public View getView(int position, View view, ViewGroup parent) {			
			if (view==null) {
				view = inflater.inflate(R.layout.entrylistitem, null);
			}
			TextView txtEntry = (TextView)view.findViewById(R.id.txtentry);
			TextView txtVoice = (TextView)view.findViewById(R.id.txtvoice);
			TextView txtShortDesc = (TextView)view.findViewById(R.id.txtshortdesc);
			TextView txtLevel = (TextView)view.findViewById(R.id.txtlevel);
			LinearLayout level = (LinearLayout)view.findViewById(R.id.level);
			txtEntry.setText(entries.get(position).getEntry());
			txtVoice.setText(String.format("[%s]", entries.get(position).getVoice()));
			if (isHide) {
				level.setVisibility(View.VISIBLE);
				txtShortDesc.setVisibility(View.GONE);
				txtLevel.setText(String.valueOf(entries.get(position).getLevel()));
				// button actions
				ImageButton btnUp = (ImageButton)view.findViewById(R.id.btnlevelup);
				btnUp.setTag(new Integer(position));
				btnUp.setOnClickListener(new OnClickListener() {
					public void onClick(View v) {
						Integer pos = (Integer) v.getTag();
						Entry entry = entries.get(pos.intValue()); 
						int lvalue = entry.getLevel();
						lvalue += 1;
						if (lvalue>MAXLEVEL) {
							lvalue = MAXLEVEL;
						}
						entry.setLevel(lvalue);
						adapter.notifyDataSetChanged();						
					}					
				});
				ImageButton btnDown = (ImageButton)view.findViewById(R.id.btnleveldown);
				btnDown.setTag(new Integer(position));
				btnDown.setOnClickListener(new OnClickListener() {
					public void onClick(View v) {
						Integer pos = (Integer) v.getTag();
						Entry entry = entries.get(pos.intValue()); 
						int lvalue = entry.getLevel();
						lvalue -= 1;
						if (lvalue<0) {
							lvalue = 0;
						}						
						entry.setLevel(lvalue);
						adapter.notifyDataSetChanged();						
					}					
				});				
			} else {
				level.setVisibility(View.GONE);
				txtShortDesc.setVisibility(View.VISIBLE);				
				txtShortDesc.setText(entries.get(position).getShortdesc());
			}			
			return view;
		}    	
    }
    
}
